package com.yejiarong.weather.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.util.DateUtils;
import com.yejiarong.common.constant.ElasticConstants;
import com.yejiarong.common.tools.HttpResult;
import com.yejiarong.common.tools.Pagination;
import com.yejiarong.common.validate.ValidateUtils;
import com.yejiarong.elasticsearch.api.bean.request.GetRequestForm;
import com.yejiarong.elasticsearch.api.bean.request.SearchRequestForm;
import com.yejiarong.elasticsearch.api.bean.request.query.Query;
import com.yejiarong.elasticsearch.api.bean.response.SearchPageResult;
import com.yejiarong.elasticsearch.api.enums.QueryType;
import com.yejiarong.elasticsearch.api.service.ElasticService;
import com.yejiarong.weather.bean.dto.FutureDayWeatherDto;
import com.yejiarong.weather.bean.dto.WeatherRegionCodeDto;
import com.yejiarong.weather.bean.vo.FutureDayWeatherVo;
import com.yejiarong.weather.service.IFutureWeatherService;
import com.yejiarong.weather.service.IWeatherRegionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.*;

/**
 * @author YeJR
 */
@Slf4j
@Service
public class FutureWeatherServiceImpl implements IFutureWeatherService {

    private final IWeatherRegionService weatherRegionService;

    private final ElasticService elasticService;

    public FutureWeatherServiceImpl(IWeatherRegionService weatherRegionService, ElasticService elasticService) {
        this.weatherRegionService = weatherRegionService;
        this.elasticService = elasticService;
    }

    /**
     * 查询未来的天气
     *
     * @param dto dto
     * @return 天气信息
     */
    @Override
    public FutureDayWeatherVo getFutureDayWeatherVo(FutureDayWeatherDto dto) {
        ValidateUtils.valid(dto);

        // 查询一下code，校验
        WeatherRegionCodeDto weatherRegionCodeDto = new WeatherRegionCodeDto();
        weatherRegionCodeDto.setProvince(dto.getProvince());
        weatherRegionCodeDto.setCity(dto.getCity());
        weatherRegionCodeDto.setCounty(dto.getCounty());
        weatherRegionService.getRegionCode(weatherRegionCodeDto);

        // 校验下时间
        LocalDate date = DateUtils.parseLocalDate(dto.getDate());
        ValidateUtils.isTrue(!date.isBefore(LocalDate.now()), "此接口不能用于查询过去的天气情况");

        // "天"级别的查询
        String dayWeatherId = dto.getProvince() + ":" + dto.getCity() + ":" + dto.getCounty() + ":" + dto.getDate();
        GetRequestForm getRequestForm = new GetRequestForm();
        getRequestForm.setIndex(ElasticConstants.WEATHER_DAY_DATA);
        getRequestForm.setDocumentId(dayWeatherId);
        HttpResult<Map<String, Object>> dayDocResult = elasticService.getDocumentById(getRequestForm);

        ValidateUtils.isTrue(Objects.nonNull(dayDocResult) && dayDocResult.isSuccess() && MapUtils.isNotEmpty(dayDocResult.getData()), "查询不到天气情况");

        // "小时"级别的天气查询
        Query query1 = new Query();
        query1.setType(QueryType.MATCH_PHRASE);
        query1.setField("time");
        query1.setValues(List.of(date));

        Query query2 = new Query();
        query2.setType(QueryType.TERM);
        query2.setField("province.enum");
        query2.setValues(List.of(dto.getProvince()));

        Query query3 = new Query();
        query3.setType(QueryType.TERM);
        query3.setField("city.enum");
        query3.setValues(List.of(dto.getCity()));

        Query query4 = new Query();
        query4.setType(QueryType.TERM);
        query4.setField("county.enum");
        query4.setValues(List.of(dto.getCounty()));

        Pagination pagination = new Pagination();
        pagination.setPageNo(1);
        pagination.setPageSize(100);

        SearchRequestForm searchRequestForm = new SearchRequestForm();
        searchRequestForm.setIndex(ElasticConstants.WEATHER_HOUR_DATA);
        searchRequestForm.setQueries(List.of(query1, query2, query3, query4));
        searchRequestForm.setPagination(pagination);

        HttpResult<SearchPageResult> searchPageResult = elasticService.searchDocument(searchRequestForm);

        // 解析结果
        FutureDayWeatherVo futureDayWeatherVo = JSONObject.parseObject(JSONObject.toJSONString(dayDocResult.getData().get("source")), FutureDayWeatherVo.class);
        if (Objects.nonNull(searchPageResult) && searchPageResult.isSuccess() && Objects.nonNull(searchPageResult.getData())) {
            List<Map<String, Object>> mapList = Optional.ofNullable(searchPageResult.getData().getList()).orElseGet(ArrayList::new);
            List<FutureDayWeatherVo.FutureHourWeather> futureHourWeathers = new ArrayList<>(mapList.size());
            for (Map<String, Object> map : mapList) {
                FutureDayWeatherVo.FutureHourWeather futureHourWeather = new FutureDayWeatherVo.FutureHourWeather();
                futureHourWeather.setTime(DateUtils.parseDate(MapUtils.getString(map, "time")));
                futureHourWeather.setOverallWeather(MapUtils.getString(map, "overallWeather"));
                futureHourWeather.setTemperature(MapUtils.getDouble(map, "temperature"));
                futureHourWeather.setWindDirection(MapUtils.getString(map, "windDirection"));
                futureHourWeather.setWindSpeed(MapUtils.getString(map, "windSpeed"));
                futureHourWeathers.add(futureHourWeather);
            }
            // 根据时间重新排序
            futureHourWeathers.sort(Comparator.comparing(FutureDayWeatherVo.FutureHourWeather::getTime));
            futureDayWeatherVo.setFutureHourWeathers(futureHourWeathers);
        }

        return futureDayWeatherVo;
    }
}
